#include "key_debounce.h"

/**
 * ************************************************************************
 * @brief 使用步骤
 * 1. 定时器/任务中调用 Key_DebounceService_10ms()
 * 2. 初始化模块 Ket_Init()
 * 3. 定时器/任务中调用 Key_Scand()
 * ************************************************************************
 */
// 定义一个常量，表示去抖时间（单位为50毫秒）
#define DEBOUNCE_TIME_10MS              5
// 定义一个常量，表示默认长按时间（单位为2000毫秒）
#define DEFAULT_LONGPRESS_TIME_10MS     200
// 定义一个名为KeyIndex_t的枚举类型，表示按键索引 
typedef enum {
    KeyIndex_Smoothie,
    KeyIndex_Pluse,
 
    KeyIndex_Max
} KeyIndex_t;
 
static uint8_t SmoothieKey_GetIO(void);
static uint8_t PluseKey_GetIO(void);
// 定义一个名为KeyInfo_Array的常量数组，用于存储按键信息
const KeyInfo_t KeyInfo_Array[KeyIndex_Max] = {
    /* {LongPressTime, ZeroIsPress, GetIOFunc(Must not NULL)} */
    {0, 1, SmoothieKey_GetIO},
    {100, 0, PluseKey_GetIO},
};
// 定义一个名为KeyValue_Array的数组，用于存储按键的状态
static Key_t KeyValue_Array[KeyIndex_Max];
// 以下代码用于测试示例，定义了GPIO端口和引脚的宏定义
#define SmoothieKey_GPIO_PORT GPIOB
#define PluseKey_GPIO_PORT GPIOB
#define SmoothieKey_GPIO_PIN GPIO_1
#define PluseKey_GPIO_PIN GPIO_2
// 定义两个宏定义，用于获取顺滑键和脉冲键的IO状态
#define IO_SmoothieKey HAL_GPIO_ReadPin(SmoothieKey_GPIO_PORT, SmoothieKey_GPIO_PIN)
#define IO_PluseKey HAL_GPIO_ReadPin(PluseKey_GPIO_PORT, PluseKey_GPIO_PIN)
// 定义一个名为Key_Scand的函数，用于扫描按键的状态
void Key_Scand(void) {
    uint8_t i = 0;
    uint8_t IOState = 0;
    // 循环遍历所有按键
    for (i = 0; i < KeyIndex_Max; ++i) {
        // 循环遍历所有按键
        IOState = KeyInfo_Array[i].GetIOFunc();
        // 如果IO状态非零，则将其设置为1
        IOState = (KeyInfo_Array[i].ZeroIsPress ? (!IOState) : (IOState));
        // 如果IO状态非零，则将其设置为1
        if (KeyValue_Array[i].CurrIOState != IOState) {
            KeyValue_Array[i].CurrIOState = IOState;
            KeyValue_Array[i].DebounceCounter = DEBOUNCE_TIME_10MS;
        }
 
        // 根据IO状态和ZeroIsPress参数判断按键状态
        if (KeyValue_Array[i].LastIOState != KeyValue_Array[i].CurrIOState) {
            if (KeyValue_Array[i].DebounceCounter == 0) {
                if ((KeyValue_Array[i].CurrIOState) && (!KeyValue_Array[i].LastIOState)) {
                    KeyValue_Array[i].State = KeyState_ShortPress;
                    // 如果LongPressTime不为零，则设置消抖计数器为LongPressTime，否则设置为DEFAULT_LONGPRESS_TIME_10MS
                    if (KeyInfo_Array[i].LongPressTime) {
                        KeyValue_Array[i].DebounceCounter = KeyInfo_Array[i].LongPressTime;
                    } else {
                        KeyValue_Array[i].DebounceCounter = DEFAULT_LONGPRESS_TIME_10MS;
                    }
                } else if ((!KeyValue_Array[i].CurrIOState) && (KeyValue_Array[i].LastIOState)) {
                    KeyValue_Array[i].State = KeyState_Release;
                } else {
                    KeyValue_Array[i].State = KeyState_None;
                }
                // 更新上次IO状态
                KeyValue_Array[i].LastIOState = KeyValue_Array[i].CurrIOState;
            }
        }
 
        // 等待长按
        if (KeyValue_Array[i].State == KeyState_ShortPress) {
            if (KeyValue_Array[i].DebounceCounter == 0) {
                KeyValue_Array[i].State = KeyState_LongPress;
            }
        }
    }
}
/**
 * ************************************************************************
 * @brief 定义一个名为Key_DebounceService_10ms的函数，用于每10ms进行一次按键消抖处理
 * ************************************************************************
 */
void Key_DebounceService_10ms(void) {
    uint8_t i;
    for (i = 0; i < KeyIndex_Max; ++i) {
        if (KeyValue_Array[i].DebounceCounter) {
            KeyValue_Array[i].DebounceCounter--;
        }
    }
}
 
/**
 * ************************************************************************
 * @brief 定义一个名为SmoothieKey_GetIO的函数，用于获取SmoothieKey的IO状态
 * @return uint8_t 
 * ************************************************************************
 */
static uint8_t SmoothieKey_GetIO(void) {
    /* 驱动抽象层接口，根据不同硬件平台接口获取IO状态值
     * 如：STM32平台 HAL_GPIO_ReadPin(SmoothieKey_GPIO_PORT, SmoothieKey_GPIO_PIN)
     */
    return IO_SmoothieKey;
}
/**
 * ************************************************************************
 * @brief 定义一个名为SmoothieKey_GetState的函数，用于获取SmoothieKey的状态
 * @return KeyState_t 
 * ************************************************************************
 */
KeyState_t SmoothieKey_GetState(void) {
    return KeyValue_Array[KeyIndex_Smoothie].State;
}
/**
 * ************************************************************************
 * @brief 定义一个名为PluseKey_GetIO的函数，用于获取PluseKey的IO状态
 * @return uint8_t 
 * ************************************************************************
 */
static uint8_t PluseKey_GetIO(void) {
    return IO_PluseKey;
}
/**
 * ************************************************************************
 * @brief 定义一个名为PluseKey_GetState的函数，用于获取PluseKey的状态
 * @return KeyState_t 
 * ************************************************************************
 */
KeyState_t PluseKey_GetState(void) {
    return KeyValue_Array[KeyIndex_Pluse].State;
}
/**
 * ************************************************************************
 * @brief 定义一个名为KeyInit的函数，用于初始化按键模块
 * ************************************************************************
 */
void Key_Init(void) {
    uint8_t i = 0;
    for(i = 0; i < KeyIndex_Max; ++i) {
        KeyValue_Array[i].CurrIOState = 0;
        KeyValue_Array[i].LastIOState = 0;
        KeyValue_Array[i].DebounceCounter = 0;
        KeyValue_Array[i].State = KeyState_None;
    }
}
